package classconverstation.cscl.ist.psu.edu.server;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Vector;

class ConnectionReaper extends Thread {

	private JDBCConnectionPool pool;
	private final long delay=300000;

	ConnectionReaper(JDBCConnectionPool pool) {
		this.pool=pool;
	}

	public void run() {
		while(true) {
			try {
				sleep(delay);
			} catch( InterruptedException e) { }
			pool.reapConnections();
		}
	}
}

public class JDBCConnectionPool {

	private Vector<JDBCConnection> connections;
	private String url, user, password;
	final private long timeout=60000;
	private ConnectionReaper reaper;
	final private int poolsize=10;

	public JDBCConnectionPool(String url, String user, String password) {
		this.url = url;
		this.user = user;
		this.password = password;
		connections = new Vector<JDBCConnection>(poolsize);
		reaper = new ConnectionReaper(this);
		reaper.start();
	}

	public synchronized void reapConnections() {

		long stale = System.currentTimeMillis() - timeout;
		Enumeration<JDBCConnection> connlist = connections.elements();

		while((connlist != null) && (connlist.hasMoreElements())) {
			JDBCConnection conn = connlist.nextElement();

			if((conn.inUse()) && (stale >conn.getLastUse()) && 
					(!conn.validate())) {
				removeConnection(conn);
			}
		}
	}

	public synchronized void closeConnections() {

		Enumeration<JDBCConnection> connlist = connections.elements();

		while((connlist != null) && (connlist.hasMoreElements())) {
			JDBCConnection conn = connlist.nextElement();
			removeConnection(conn);
		}
	}

	private synchronized void removeConnection(JDBCConnection conn) {
		connections.removeElement(conn);
	}


	public synchronized Connection getConnection() throws SQLException {

		JDBCConnection c;
		for(int i = 0; i < connections.size(); i++) {
			c = connections.elementAt(i);
			if (c.lease()) {
				return c;
			}
		}

		Connection conn = DriverManager.getConnection(url, user, password);
		c = new JDBCConnection(conn, this);
		c.lease();
		connections.addElement(c);
		return c;
	} 

	public synchronized void returnConnection(JDBCConnection conn) {
		conn.expireLease();
	}
}
